/**
 * 
 */
package com.suman.bbcticker.service;

import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.text.Html;
import android.text.Spanned;
import android.util.Log;
import android.widget.RemoteViews;

import com.suman.bbcticker.FeedItem;
import com.suman.bbcticker.R;
import com.suman.bbcticker.RssFeed;
import com.suman.bbcticker.configure.PreferenceLauncherActivity;
import com.suman.bbcticker.parser.RssFeedHandler;

/**
 * @author ShivakP
 */
public class RssReaderService extends Service {
	private static final String SPACE_SEPARATOR = "   ";
	public static final String FEED_FOR_FIRST_TIME = "Feed For FirstTime";
	private static final String TAG = "RssReaderService";
	protected static final String PACKAGE_NAME_FOR_MSG_HANDLER = null;
	public static String CURRENT_FEED = "CURRENT_FEED";
	public static String SITE_BBC_NEWS = "SITE_BBCNEWS";
	public static RssFeed currentRssFeedObject = new RssFeed();

	private static int notificationId = 0;
	public static HashMap<Integer, Date> alarmTriggerTimeMap = new HashMap<Integer, Date>();

	private static String NETWORK_PROB_TEXT = "Sorry for Inconvenience.Please Wait.Waiting for Network Connection to become available.";

	@Override
	public void onStart(Intent intent, int startId) {
		try {

			Bundle extras = intent.getExtras();
			int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
			if (extras != null) {
				mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
			}
			AppDataHolder appDataHolder = new AppDataHolder();
			appDataHolder.setAppWidgetId(mAppWidgetId);
			appDataHolder.setContext(this);
			appDataHolder.setIntent(intent);
			new RssFeedInvokerTask().execute(appDataHolder);

		} catch (Throwable e) {
			Log.e(TAG, "Some throwable.." + e);
		}

	}

	public RemoteViews buildUpdate(int appWidgetId) {
		SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
		Context context = this;
		boolean feedAlert = sharedPreferences.getBoolean(PreferenceLauncherActivity.TICKER_ALERTTYPE_NOTIFICATION_KEY, false);

		String currentFeed = sharedPreferences.getString(PreferenceLauncherActivity.PREF_PREFIX_KEY + appWidgetId + CURRENT_FEED,
				FEED_FOR_FIRST_TIME);

		String rssFeedUrl = sharedPreferences.getString(PreferenceLauncherActivity.TICKER_ALERTTYPE_SITESELECTED_KEY,
				"http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/world/rss.xml");
		String webPageUrl = "http://www.bbc.co.uk";
		String widgetImage = SITE_BBC_NEWS;

		String feedRefreshTime = sharedPreferences.getString(PreferenceLauncherActivity.TICKER_ALERTTYPE_FEEDREFRESHTIME_KEY, "60");
		RssFeed rssFeed = invokeRssFeedService(rssFeedUrl, appWidgetId, feedRefreshTime);
		currentRssFeedObject = rssFeed;
		StringBuffer completeFeed = transformRssFeedToString(rssFeed);
		RemoteViews updateViews = null;

		if (completeFeed != null) {
			// This is when some problem with network happens and nothing comes
			// back
			if ("".equalsIgnoreCase(completeFeed.toString())) {

				updateViews = doActionWhenHostIsResolved(context, appWidgetId, sharedPreferences, feedAlert, currentFeed, webPageUrl,
						widgetImage, new StringBuffer(NETWORK_PROB_TEXT), rssFeed);

			} else {
				updateViews = doActionWhenHostIsResolved(context, appWidgetId, sharedPreferences, feedAlert, currentFeed, webPageUrl,
						widgetImage, completeFeed, rssFeed);
			}

		}

		return updateViews;

	}

	private RemoteViews doActionWhenHostIsResolved(Context context, int appWidgetId, SharedPreferences prefs, boolean feedAlert,
			String currentFeed, String webPageUrl, String widgetImage, StringBuffer completeFeed, RssFeed rssFeed) {
		RemoteViews updateViews;
		updateViews = new RemoteViews(context.getPackageName(), R.layout.widget_word);
		

		updateViews.setTextViewText(R.id.word_title, completeFeed.toString());
		
		PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(this, DisplayNewsActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0);
		updateViews.setOnClickPendingIntent(R.id.icon, pendingIntent);
		updateViews.setImageViewResource(R.id.icon, R.drawable.bbcnews_logo);
		
		updateViews.setOnClickPendingIntent(R.id.readmoreicon, pendingIntent);
		updateViews.setImageViewResource(R.id.readmoreicon, R.drawable.readmoreicon);
		
		
		

		raiseNotificationAndsavePrefs(appWidgetId, prefs, feedAlert, currentFeed, completeFeed, rssFeed);
		return updateViews;
	}

	private void raiseNotificationAndsavePrefs(int appWidgetId, SharedPreferences prefs, boolean feedAlert, String currentFeed,
			StringBuffer completeFeed, RssFeed currentRssFeedObj) {
		if (feedAlert) {

			// Dont raise an alert when system boots up initially(After adding
			// widget)
			String[] changedFeedItemsAsArray = getArrayRepresentationForChangedFeed(currentFeed, completeFeed.toString());
			boolean doWeNeedToNotifyUser = doWeNeedToNotifyUser(currentFeed, completeFeed, changedFeedItemsAsArray);
			if (doWeNeedToNotifyUser) {
				List<FeedItem> feedChangeList = new ArrayList<FeedItem>();
				for (String changedFeedAsString : changedFeedItemsAsArray) {
					FeedItem feedItem = currentRssFeedObj.getFeedItemBasedOnTitle(changedFeedAsString.trim());
					if (checkForNull(feedItem)) {
						feedChangeList.add(feedItem);

					}
				}

				if (feedChangeList.size() > 0) {
					raiseNotification(prefs, feedChangeList);
				}

			}

		}

		SharedPreferences.Editor editPrefs = prefs.edit();
		editPrefs.putString(PreferenceLauncherActivity.PREF_PREFIX_KEY + appWidgetId + CURRENT_FEED, completeFeed.toString());
		editPrefs.commit();

	}

	private void raiseNotification(SharedPreferences sharedPreferences, List<FeedItem> feedChangeList) {

		boolean notificationSelected = sharedPreferences.getBoolean(PreferenceLauncherActivity.TICKER_ALERTTYPE_NOTIFICATION_KEY, false);
		if (notificationSelected) {
			boolean notificationSound = sharedPreferences.getBoolean(PreferenceLauncherActivity.TICKER_ALERTTYPE_SOUND_KEY, false);
			boolean notificationVibrate = sharedPreferences.getBoolean(PreferenceLauncherActivity.TICKER_ALERTTYPE_VIBRATE_KEY, false);
			Log.e(TAG, "notificationSound and notificationVibrate are.."+notificationSound + ","+ notificationVibrate);

			NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
			for (FeedItem changedFeedItem : feedChangeList) {
				Notification notification = new Notification(R.drawable.alert_small, changedFeedItem.getTitle(), System.currentTimeMillis());
				RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.widget_notification);
				contentView.setTextViewText(R.id.newswidgetnotificationheadline, changedFeedItem.getTitle());
				contentView.setTextViewText(R.id.newswidgetnotificationdescription, changedFeedItem.getDescription());
				notification.contentView = contentView;
				if (changedFeedItem.getLink() != null) {
					Intent defineIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(changedFeedItem.getLink()));
					PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, defineIntent, 0);
					notification.contentIntent = pendingIntent;
				}

				if (notificationSound) {
					notification.defaults |= Notification.DEFAULT_SOUND;
				}
				if (notificationVibrate) {
					notification.defaults |= Notification.DEFAULT_VIBRATE;
				}
				notification.flags |= Notification.FLAG_AUTO_CANCEL;
				nm.notify(R.string.app_notification_id + (++notificationId), notification);

			}
		}

	}

	private boolean checkForNull(FeedItem changedFeedItem) {
		return (changedFeedItem != null && changedFeedItem.getDescription() != null && changedFeedItem.getTitle() != null && changedFeedItem
				.getLink() != null);

	}

	private boolean doWeNeedToNotifyUser(String currentFeed, StringBuffer completeFeed, String[] changedFeedItemsAsArray) {
		return changedFeedItemsAsArray != null && changedFeedItemsAsArray.length > 0 && !FEED_FOR_FIRST_TIME.equalsIgnoreCase(currentFeed)
				&& !completeFeed.toString().startsWith(NETWORK_PROB_TEXT) && !currentFeed.toString().startsWith(NETWORK_PROB_TEXT);
	}

	private String[] getArrayRepresentationForChangedFeed(String currentFeed, String completeFeed) {
		String[] currentFeedAsTokens = currentFeed.split("\\s{3}");
		String[] completeFeedAsTokens = completeFeed.split("\\s{3}");
		ArrayList<String> currentFeedAsTokensAsList = new ArrayList<String>(Arrays.asList(currentFeedAsTokens));
		ArrayList<String> completeFeedAsTokensAsList = new ArrayList<String>(Arrays.asList(completeFeedAsTokens));
		completeFeedAsTokensAsList.removeAll(currentFeedAsTokensAsList);
		String[] array = (String[]) completeFeedAsTokensAsList.toArray(new String[completeFeedAsTokensAsList.size()]);

		return array;
	}

	protected StringBuffer transformRssFeedToString(RssFeed rssFeed) {
		StringBuffer completeFeed = new StringBuffer();
		if (rssFeed != null) {
			for (FeedItem feedItem : rssFeed.getFeedList()) {
				String formattedString = MessageFormat.format("<a href=\"{0}\">{1}</a>  ", feedItem.getLink(), feedItem.getTitle());
				Spanned fromHtml = Html.fromHtml(formattedString);
				completeFeed.append(fromHtml);
				completeFeed.append(SPACE_SEPARATOR);
			}
		}
		return completeFeed;
	}

	private RssFeed invokeRssFeedService(String rssFeedUrl, int mAppWidgetId, String feedRefreshTime) {
		RssFeed rssFeed = null;
		if (!"".equalsIgnoreCase(rssFeedUrl)) {
			

			RssFeedHandler rssFeedHandler = new RssFeedHandler();
			try {
				rssFeed = rssFeedHandler.createFeed(new URL(rssFeedUrl));
				updateAlarmTriggermap(mAppWidgetId, Integer.parseInt(feedRefreshTime));
			} catch (MalformedURLException e) {
				Log.e(TAG, "Malformed URl Exception", e);
			} catch (Throwable e) {
				updateAlarmTriggermap(mAppWidgetId, 0);
				Log.e(TAG, "Some throwable exception", e);
			}
		}
		return rssFeed;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Service#onBind(android.content.Intent)
	 */
	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	private class RssFeedInvokerTask extends AsyncTask<AppDataHolder, Void, AppDataHolder> {
		@Override
		protected void onPostExecute(AppDataHolder appDataHolder) {
			try {

				if (appDataHolder.getRemoteViews() != null) {
					AppWidgetManager manager = AppWidgetManager.getInstance(appDataHolder.getContext());
					manager.updateAppWidget(appDataHolder.getAppWidgetId(), appDataHolder.getRemoteViews());
				}

			} catch (Throwable t) {
				Log.e(TAG, "Some throwable exception", t);
			}

		}

		@Override
		protected AppDataHolder doInBackground(AppDataHolder... appDataHolderParamArray) {
			AppDataHolder appDataHolder = new AppDataHolder();
			try {

				AppDataHolder appDataHolderParam = appDataHolderParamArray[0];
				Bundle extras = appDataHolderParam.getIntent().getExtras();
				int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
				if (extras != null) {
					mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
				}
				RemoteViews remoteViews = buildUpdate(mAppWidgetId);
				appDataHolder.setRemoteViews(remoteViews);
				appDataHolder.setIntent(appDataHolderParam.getIntent());
				appDataHolder.setContext(appDataHolderParam.getContext());
				appDataHolder.setAppWidgetId(mAppWidgetId);

			} catch (Throwable t) {
				Log.e(TAG, "Some throwable exception", t);
			}
			return appDataHolder;

		}

	}

	private class AppDataHolder {
		private RemoteViews remoteViews;
		private Intent intent;
		private Context context;
		private int appWidgetId;

		public void setRemoteViews(RemoteViews remoteViews) {
			this.remoteViews = remoteViews;
		}

		public RemoteViews getRemoteViews() {
			return remoteViews;
		}

		public void setIntent(Intent intent) {
			this.intent = intent;
		}

		public Intent getIntent() {
			return intent;
		}

		public void setContext(Context context) {
			this.context = context;
		}

		public Context getContext() {
			return context;
		}

		public void setAppWidgetId(int appWidgetId) {
			this.appWidgetId = appWidgetId;
		}

		public int getAppWidgetId() {
			return appWidgetId;
		}

	}

	private void updateAlarmTriggermap(int appWidgetId, int feedRefreshTimeInMins) {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MINUTE, feedRefreshTimeInMins);
		Date nextAlarmTriggerTime = calendar.getTime();
		alarmTriggerTimeMap.put(appWidgetId, nextAlarmTriggerTime);
	}

}
